package com.jzcn.admin.shiro;

import com.jzcn.common.exceptions.BusinessException;
import com.jzcn.common.utils.Md5Utils;
import com.jzcn.domain.SysUser;
import com.jzcn.service.SysRoleResourcesService;
import com.jzcn.service.SysUserRoleService;
import com.jzcn.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

@Slf4j
public class CustomRelam extends AuthorizingRealm {

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysRoleResourcesService sysRoleResourcesService;

    /**
     * 为当前用户授权
     * 先执行 doGetAuthenticationInfo(token)
     * 然后执行此方法
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("进入授权函数doGetAuthorizationInfo");
        //获取用户信息
        SysUser user = (SysUser) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        List<String> roleList = sysUserRoleService.findRoleListByUserId(user.getId());
        List<String> permList = sysRoleResourcesService.findPermListByUserId(user.getId());
        simpleAuthorizationInfo.addRoles(roleList);
        simpleAuthorizationInfo.addStringPermissions(permList);
        log.info("授权用户:[{}]", user);
        log.info("用户id[{}] 拥有角色[{}]", user.getId(), roleList);
        log.info("用户id[{}] 拥有权限[{}]", user.getId(), permList);
        return simpleAuthorizationInfo;
    }

    /**
     * 验证当前登录的用户
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        String username = usernamePasswordToken.getUsername();
        String password = new String(usernamePasswordToken.getPassword());
        log.info("进入登录认证，账号[{}],密码[{}]", username, password);
        //获取用户信息
        SysUser sysUser = sysUserService.getUserName(username);
        // 根据用户名获取用户信息
        if (Objects.isNull(sysUser)) {
            throw new BusinessException("用户名或密码有误");
        }
        //这里验证authenticationToken和simpleAuthenticationInfo的信息
        return new SimpleAuthenticationInfo(sysUser, password, username);
    }

    public void clearCachedAuthorizationInfo() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }
}
